<!DOCTYPE html>
<html lang=zh>
<head>
    <!-- so meta -->
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="HandheldFriendly" content="True">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
    <meta name="description" content="应用场景我们希望通过缓存来减少对关系型数据库的查询次数，减轻数据库压力。在执行DAO类的select***(), query***()方法时，先从Redis中查询有没有缓存数据，如果有则直接从Redis拿到结果，如果没有再向数据库发起查询请求取数据。 序列化问题要把对象做为key-value对保存在redis中，就必须要解决对象的序列化问题。Spring Data Redis给我们提供了一些现成的">
<meta property="og:type" content="article">
<meta property="og:title" content="使用Spring Cache + Redis + Jackson Serializer缓存数据库查询结果中序列化问题的处理">
<meta property="og:url" content="https:&#x2F;&#x2F;fengzxia.gitee.io&#x2F;posts&#x2F;f6f65c4b.html">
<meta property="og:site_name" content="只是学习学习的博客">
<meta property="og:description" content="应用场景我们希望通过缓存来减少对关系型数据库的查询次数，减轻数据库压力。在执行DAO类的select***(), query***()方法时，先从Redis中查询有没有缓存数据，如果有则直接从Redis拿到结果，如果没有再向数据库发起查询请求取数据。 序列化问题要把对象做为key-value对保存在redis中，就必须要解决对象的序列化问题。Spring Data Redis给我们提供了一些现成的">
<meta property="og:locale" content="zh_CN">
<meta property="article:published_time" content="2019-04-11T06:50:05.000Z">
<meta property="article:modified_time" content="2020-04-16T12:11:09.457Z">
<meta property="article:author" content="只是学习学习">
<meta property="article:tag" content="序列化">
<meta name="twitter:card" content="summary">
    
    
        
          
              <link rel="shortcut icon" href="/images/favicon.ico">
          
        
        
          
            <link rel="icon" type="image/png" href="/images/favicon-192x192.png" sizes="192x192">
          
        
        
          
            <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon.png">
          
        
    
    <!-- title -->
    <title>使用Spring Cache + Redis + Jackson Serializer缓存数据库查询结果中序列化问题的处理</title>
    <!-- styles -->
    
<link rel="stylesheet" href="/css/style.css">

    <!-- persian styles -->
    
      
<link rel="stylesheet" href="/css/rtl.css">

    
    <!-- rss -->
    
    
    
<meta name="generator" content="Hexo 4.1.1"></head>

<body class="max-width mx-auto px3 ltr">
    
      <div id="header-post">
  <a id="menu-icon" href="#"><i class="fas fa-bars fa-lg"></i></a>
  <a id="menu-icon-tablet" href="#"><i class="fas fa-bars fa-lg"></i></a>
  <a id="top-icon-tablet" href="#" onclick="$('html, body').animate({ scrollTop: 0 }, 'fast');" style="display:none;"><i class="fas fa-chevron-up fa-lg"></i></a>
  <span id="menu">
    <span id="nav">
      <ul>
         
          <li><a href="/">主页</a></li>
         
          <li><a href="/archives/">归档</a></li>
         
          <li><a href="/categories/">分类</a></li>
         
          <li><a href="/tags/">标签</a></li>
         
          <li><a href="/search/">搜索</a></li>
         
          <li><a href="/about/">关于</a></li>
         
          <li><a href="/friend_ship/">友链</a></li>
        
      </ul>
    </span>
    <br/>
    <span id="actions">
      <ul>
        
        <li><a class="icon" href="/posts/bb5d726a.html"><i class="fas fa-chevron-left" aria-hidden="true" onmouseover="$('#i-prev').toggle();" onmouseout="$('#i-prev').toggle();"></i></a></li>
        
        
        <li><a class="icon" href="/posts/90da3b9e.html"><i class="fas fa-chevron-right" aria-hidden="true" onmouseover="$('#i-next').toggle();" onmouseout="$('#i-next').toggle();"></i></a></li>
        
        <li><a class="icon" href="#" onclick="$('html, body').animate({ scrollTop: 0 }, 'fast');"><i class="fas fa-chevron-up" aria-hidden="true" onmouseover="$('#i-top').toggle();" onmouseout="$('#i-top').toggle();"></i></a></li>
        <li><a class="icon" href="#"><i class="fas fa-share-alt" aria-hidden="true" onmouseover="$('#i-share').toggle();" onmouseout="$('#i-share').toggle();" onclick="$('#share').toggle();return false;"></i></a></li>
      </ul>
      <span id="i-prev" class="info" style="display:none;">上一篇</span>
      <span id="i-next" class="info" style="display:none;">下一篇</span>
      <span id="i-top" class="info" style="display:none;">返回顶部</span>
      <span id="i-share" class="info" style="display:none;">分享文章</span>
    </span>
    <br/>
    <div id="share" style="display: none">
      <ul>
  <li><a class="icon" href="http://www.facebook.com/sharer.php?u=https://fengzxia.gitee.io/posts/f6f65c4b.html" target="_blank" rel="noopener"><i class="fab fa-facebook " aria-hidden="true"></i></a></li>
  <li><a class="icon" href="https://twitter.com/share?url=https://fengzxia.gitee.io/posts/f6f65c4b.html&text=使用Spring Cache + Redis + Jackson Serializer缓存数据库查询结果中序列化问题的处理" target="_blank" rel="noopener"><i class="fab fa-twitter " aria-hidden="true"></i></a></li>
  <li><a class="icon" href="http://www.linkedin.com/shareArticle?url=https://fengzxia.gitee.io/posts/f6f65c4b.html&title=使用Spring Cache + Redis + Jackson Serializer缓存数据库查询结果中序列化问题的处理" target="_blank" rel="noopener"><i class="fab fa-linkedin " aria-hidden="true"></i></a></li>
  <li><a class="icon" href="https://pinterest.com/pin/create/bookmarklet/?url=https://fengzxia.gitee.io/posts/f6f65c4b.html&is_video=false&description=使用Spring Cache + Redis + Jackson Serializer缓存数据库查询结果中序列化问题的处理" target="_blank" rel="noopener"><i class="fab fa-pinterest " aria-hidden="true"></i></a></li>
  <li><a class="icon" href="mailto:?subject=使用Spring Cache + Redis + Jackson Serializer缓存数据库查询结果中序列化问题的处理&body=Check out this article: https://fengzxia.gitee.io/posts/f6f65c4b.html"><i class="fas fa-envelope " aria-hidden="true"></i></a></li>
  <li><a class="icon" href="https://getpocket.com/save?url=https://fengzxia.gitee.io/posts/f6f65c4b.html&title=使用Spring Cache + Redis + Jackson Serializer缓存数据库查询结果中序列化问题的处理" target="_blank" rel="noopener"><i class="fab fa-get-pocket " aria-hidden="true"></i></a></li>
  <li><a class="icon" href="http://reddit.com/submit?url=https://fengzxia.gitee.io/posts/f6f65c4b.html&title=使用Spring Cache + Redis + Jackson Serializer缓存数据库查询结果中序列化问题的处理" target="_blank" rel="noopener"><i class="fab fa-reddit " aria-hidden="true"></i></a></li>
  <li><a class="icon" href="http://www.stumbleupon.com/submit?url=https://fengzxia.gitee.io/posts/f6f65c4b.html&title=使用Spring Cache + Redis + Jackson Serializer缓存数据库查询结果中序列化问题的处理" target="_blank" rel="noopener"><i class="fab fa-stumbleupon " aria-hidden="true"></i></a></li>
  <li><a class="icon" href="http://digg.com/submit?url=https://fengzxia.gitee.io/posts/f6f65c4b.html&title=使用Spring Cache + Redis + Jackson Serializer缓存数据库查询结果中序列化问题的处理" target="_blank" rel="noopener"><i class="fab fa-digg " aria-hidden="true"></i></a></li>
  <li><a class="icon" href="http://www.tumblr.com/share/link?url=https://fengzxia.gitee.io/posts/f6f65c4b.html&name=使用Spring Cache + Redis + Jackson Serializer缓存数据库查询结果中序列化问题的处理&description=" target="_blank" rel="noopener"><i class="fab fa-tumblr " aria-hidden="true"></i></a></li>
  <li><a class="icon" href="https://news.ycombinator.com/submitlink?u=https://fengzxia.gitee.io/posts/f6f65c4b.html&t=使用Spring Cache + Redis + Jackson Serializer缓存数据库查询结果中序列化问题的处理" target="_blank" rel="noopener"><i class="fab fa-hacker-news " aria-hidden="true"></i></a></li>
</ul>

    </div>
    <div id="toc">
      <ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#应用场景"><span class="toc-number">1.</span> <span class="toc-text">应用场景</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#序列化问题"><span class="toc-number">2.</span> <span class="toc-text">序列化问题</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#分析"><span class="toc-number">3.</span> <span class="toc-text">分析</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#总结"><span class="toc-number">4.</span> <span class="toc-text">总结</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Jackson2JsonRedisSerializer和GenericJackson2JsonRedisSerializer的区别"><span class="toc-number">5.</span> <span class="toc-text">Jackson2JsonRedisSerializer和GenericJackson2JsonRedisSerializer的区别</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#一、使用Jackson2JsonRedisSerializer序列化反序列化带泛型的List数据"><span class="toc-number">5.1.</span> <span class="toc-text">一、使用Jackson2JsonRedisSerializer序列化反序列化带泛型的List数据</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#二、使用GenericJackson2JsonRedisSerializer序列化反序列化带泛型的List数据"><span class="toc-number">5.2.</span> <span class="toc-text">二、使用GenericJackson2JsonRedisSerializer序列化反序列化带泛型的List数据</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#四、GenericJackson2JsonRedisSerializer和Jackson2JsonRedisSerializerdo效率"><span class="toc-number">5.3.</span> <span class="toc-text">四、GenericJackson2JsonRedisSerializer和Jackson2JsonRedisSerializerdo效率</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#总结-1"><span class="toc-number">5.4.</span> <span class="toc-text">总结</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#demo测试地址"><span class="toc-number">6.</span> <span class="toc-text">demo测试地址</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#参考"><span class="toc-number">7.</span> <span class="toc-text">参考</span></a></li></ol>
    </div>
  </span>
</div>

    
    <div class="content index py4">
        
        <article class="post" itemscope itemtype="http://schema.org/BlogPosting">
  <header>
    
    <h1 class="posttitle" itemprop="name headline">
        使用Spring Cache + Redis + Jackson Serializer缓存数据库查询结果中序列化问题的处理
    </h1>



    <div class="meta">
      <span class="author" itemprop="author" itemscope itemtype="http://schema.org/Person">
        <span itemprop="name">只是学习学习的博客</span>
      </span>
      
    <div class="postdate">
      
        <time datetime="2019-04-11T06:50:05.000Z" itemprop="datePublished">2019-04-11</time>
        
      
    </div>


      
    <div class="article-category">
        <i class="fas fa-archive"></i>
        <a class="category-link" href="/categories/Java/">Java</a> › <a class="category-link" href="/categories/Java/Jackson/">Jackson</a> › <a class="category-link" href="/categories/Java/Redis/">Redis</a> › <a class="category-link" href="/categories/Java/Spring/">Spring</a>
    </div>


      
    <div class="article-tag">
        <i class="fas fa-tag"></i>
        <a class="tag-link" href="/tags/%E5%BA%8F%E5%88%97%E5%8C%96/" rel="tag">序列化</a>
    </div>


    </div>
  </header>
  

  <div class="content"itemprop ="articleBody">
    <h2 id="应用场景"><a href="#应用场景" class="headerlink" title="应用场景"></a>应用场景</h2><p>我们希望通过缓存来减少对关系型数据库的查询次数，减轻数据库压力。在执行DAO类的<code>select***()</code>, <code>query***()</code>方法时，先从Redis中查询有没有缓存数据，如果有则直接从Redis拿到结果，如果没有再向数据库发起查询请求取数据。</p>
<h2 id="序列化问题"><a href="#序列化问题" class="headerlink" title="序列化问题"></a>序列化问题</h2><p>要把<code>对象</code>做为<code>key-value</code>对保存在redis中，就必须要解决对象的序列化问题。Spring Data Redis给我们提供了一些现成的方案：</p>
<ul>
<li><p><code>JdkSerializationRedisSerializer</code>. 使用JDK提供的序列化功能。 优点是反序列化时不需要提供类型信息(class)，但缺点是序列化后的结果非常庞大，是JSON格式的5倍左右，这样就会消耗redis服务器的大量内存。</p>
</li>
<li><p><code>Jackson2JsonRedisSerializer</code>. 使用Jackson库将对象序列化为JSON字符串。优点是速度快，序列化后的字符串短小精悍。但缺点也非常致命，那就是此类的构造函数中有一个类型参数，必须提供要序列化对象的类型信息(.class对象)。 通过查看源代码，发现其只在反序列化过程中用到了类型信息。</p>
</li>
<li><p><code>GenericJackson2JsonRedisSerializer</code>. 和 <code>Jackson2JsonRedisSerializer</code> 类似。但是它不需要提供序列化对象的类型信息。</p>
</li>
</ul>
<h2 id="分析"><a href="#分析" class="headerlink" title="分析"></a>分析</h2><p>如果用方案一，就必须付出缓存多占用4倍内存的代价，实在承受不起。  </p>
<p>如果用方案二，则必须给每一种domain对象都配置一个Serializer，即如果我的应用里有100种domain对象，那就必须在spring配置文件中配置100个Jackson2JsonRedisSerializer，这显然也是不现实的。</p>
<p>如果用方案三，就是为了解决Jackson必须提供类型信息的问题，可以同时支持多种不同类型的domain对象。</p>
<h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>所以选择使用<code>GenericJackson2JsonRedisSerializer</code>来配置序列化。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Bean</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> RedisCacheManager <span class="title">jsonCacheManager</span><span class="params">(RedisConnectionFactory factory)</span> </span>&#123;</span><br><span class="line">    RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()</span><br><span class="line">            .serializeValuesWith(RedisSerializationContext.SerializationPair</span><br><span class="line">                .fromSerializer(<span class="keyword">new</span> GenericJackson2JsonRedisSerializer()));</span><br><span class="line">    <span class="keyword">return</span> RedisCacheManager.builder(factory)</span><br><span class="line">            .cacheDefaults(config)</span><br><span class="line">            .build();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="Jackson2JsonRedisSerializer和GenericJackson2JsonRedisSerializer的区别"><a href="#Jackson2JsonRedisSerializer和GenericJackson2JsonRedisSerializer的区别" class="headerlink" title="Jackson2JsonRedisSerializer和GenericJackson2JsonRedisSerializer的区别"></a>Jackson2JsonRedisSerializer和GenericJackson2JsonRedisSerializer的区别</h2><h3 id="一、使用Jackson2JsonRedisSerializer序列化反序列化带泛型的List数据"><a href="#一、使用Jackson2JsonRedisSerializer序列化反序列化带泛型的List数据" class="headerlink" title="一、使用Jackson2JsonRedisSerializer序列化反序列化带泛型的List数据"></a>一、使用Jackson2JsonRedisSerializer序列化反序列化带泛型的List数据</h3><p>1、使用Jackson2JsonRedisSerializer序列化value的代码</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">redisTemplate.setKeySerializer(<span class="keyword">new</span> StringRedisSerializer());</span><br><span class="line">redisTemplate.setValueSerializer(<span class="keyword">new</span> Jackson2JsonRedisSerializer(Object<span class="class">.<span class="keyword">class</span>))</span>;</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">User user = <span class="keyword">new</span> User();</span><br><span class="line">user.setUserId(<span class="number">1</span>);</span><br><span class="line">user.setUsername(<span class="string">"张三"</span>);</span><br><span class="line">List&lt;User&gt; userList = <span class="keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line">userList.add(user);</span><br><span class="line"><span class="comment">//不能直接将对象存储进redis中否则在进行反序列化的时候会报</span></span><br><span class="line"><span class="comment">// java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to com.lx.entity.User错误</span></span><br><span class="line"><span class="comment">//可以先转为json字符串再进行存储</span></span><br><span class="line">String value = JSON.toJSONString(userList);</span><br><span class="line">redisTemplate.opsForValue().set(<span class="string">"jackson2JsonRedisSerializer"</span>, value, <span class="number">5</span>,</span><br><span class="line">        TimeUnit.MINUTES);</span><br></pre></td></tr></table></figure>
<p>2、使用Jackson2JsonRedisSerializer序列化后的数据形式</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">[</span><br><span class="line">  &#123;</span><br><span class="line">    <span class="attr">"userId"</span>:<span class="number">1</span>,</span><br><span class="line">    <span class="attr">"username"</span>:<span class="string">"张三"</span></span><br><span class="line">  &#125;</span><br><span class="line">]</span><br></pre></td></tr></table></figure>
<p>3、使用Jackson2JsonRedisSerializer反序列化时报错</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">List&lt;User&gt; userListRedis = redisTemplate.opsForValue().get(<span class="string">"jackson2JsonRedisSerializer"</span>);</span><br><span class="line">userListRedis.forEach(u -&gt; System.out.println(JSON.toJSONString(u)));</span><br></pre></td></tr></table></figure>
<p>错误信息</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to com.lx.entity.User</span><br></pre></td></tr></table></figure>
<ul>
<li>原因: <strong>序列化带泛型的数据时，会以map的结构进行存储，反序列化时不能将map解析成对象。</strong></li>
</ul>
<p>4、解决方案：序列化存储时，转成JSON字符串<br>使用<code>jackson</code>或者<code>fastjson</code>都可以，我这里使用的是<code>fastjson</code>,<br>需要的依赖</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.alibaba<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>fastjson<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.2.47<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">User user = <span class="keyword">new</span> User();</span><br><span class="line">user.setUserId(<span class="number">1</span>);</span><br><span class="line">user.setUsername(<span class="string">"张三"</span>);</span><br><span class="line">List&lt;User&gt; userList = <span class="keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line">userList.add(user);</span><br><span class="line"></span><br><span class="line">redisTemplate.opsForValue().set(<span class="string">"jackson2JsonRedisSerializer"</span>, JSON.toJSONString(userList), <span class="number">5</span>, TimeUnit.MINUTES);</span><br><span class="line"></span><br><span class="line">String res = (String) redisTemplate.opsForValue().get(<span class="string">"jackson2JsonRedisSerializer"</span>);</span><br><span class="line">JSON.parseArray(res, User<span class="class">.<span class="keyword">class</span>).<span class="title">forEach</span>(<span class="title">u</span> -&gt; <span class="title">System</span>.<span class="title">out</span>.<span class="title">println</span>(<span class="title">JSON</span>.<span class="title">toJSONString</span>(<span class="title">u</span>)))</span>;</span><br></pre></td></tr></table></figure>
<h3 id="二、使用GenericJackson2JsonRedisSerializer序列化反序列化带泛型的List数据"><a href="#二、使用GenericJackson2JsonRedisSerializer序列化反序列化带泛型的List数据" class="headerlink" title="二、使用GenericJackson2JsonRedisSerializer序列化反序列化带泛型的List数据"></a>二、使用GenericJackson2JsonRedisSerializer序列化反序列化带泛型的List数据</h3><p>1、使用GenericJackson2JsonRedisSerializer序列化value的代码</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">redisTemplate.setKeySerializer(<span class="keyword">new</span> StringRedisSerializer());</span><br><span class="line">redisTemplate.setValueSerializer(<span class="keyword">new</span> GenericJackson2JsonRedisSerializer());</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">User user = <span class="keyword">new</span> User();</span><br><span class="line">user.setUserId(<span class="number">1</span>);</span><br><span class="line">user.setUsername(<span class="string">"李四"</span>);</span><br><span class="line">List&lt;User&gt; userList = <span class="keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line">userList.add(user);</span><br><span class="line">redisTemplate.opsForValue().set(<span class="string">"genericJackson2JsonRedisSerializer"</span>,userList,<span class="number">5</span>,TimeUnit.MINUTES);</span><br></pre></td></tr></table></figure>

<p>2、使用GenericJackson2JsonRedisSerializer序列化后的数据形式</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">[</span><br><span class="line">    <span class="string">"java.util.ArrayList"</span>,</span><br><span class="line">    [</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="attr">"@class"</span>: <span class="string">"com.lx.entity.User"</span>,</span><br><span class="line">            <span class="attr">"userId"</span>: <span class="number">1</span>,</span><br><span class="line">            <span class="attr">"username"</span>: <span class="string">"李四"</span></span><br><span class="line">        &#125;</span><br><span class="line">    ]</span><br><span class="line">]</span><br></pre></td></tr></table></figure>

<p>3、使用GenericJackson2JsonRedisSerializer可以正常反序列化</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">List&lt;User&gt; userListRedis = (List&lt;User&gt;) redisTemplate.opsForValue().get(<span class="string">"genericJackson2JsonRedisSerializer"</span>);</span><br><span class="line">userListRedis.forEach(u -&gt; System.out.println(JSON.toJSONString(u)));</span><br></pre></td></tr></table></figure>

<p>4、可以正常反序列化的原因<br>使用<code>GenericJackson2JsonRedisSerializer</code>序列化时，会保存序列化的对象的包名和类名，反序列化时以这个作为标示就可以反序列化成指定的对象。</p>
<p>5、也可以以JSON字符串保存</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">redisTemplate.opsForValue().set(<span class="string">"genericJackson2JsonRedisSerializer"</span>,JSON.toJSONString(userList),<span class="number">5</span>,TimeUnit.MINUTES);</span><br><span class="line"></span><br><span class="line">List&lt;User&gt; userListRedis = (List&lt;User&gt;) redisTemplate.opsForValue().get(<span class="string">"genericJackson2JsonRedisSerializer"</span>);</span><br><span class="line">userListRedis.forEach(u -&gt; System.out.println(JSON.toJSONString(u)));</span><br></pre></td></tr></table></figure>

<h3 id="四、GenericJackson2JsonRedisSerializer和Jackson2JsonRedisSerializerdo效率"><a href="#四、GenericJackson2JsonRedisSerializer和Jackson2JsonRedisSerializerdo效率" class="headerlink" title="四、GenericJackson2JsonRedisSerializer和Jackson2JsonRedisSerializerdo效率"></a>四、GenericJackson2JsonRedisSerializer和Jackson2JsonRedisSerializerdo效率</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">User user = <span class="keyword">new</span> User();</span><br><span class="line">user.setUserId(<span class="number">1</span>);</span><br><span class="line">user.setUsername(<span class="string">"李四"</span>);</span><br><span class="line">List&lt;User&gt; userList = <span class="keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; <span class="number">10000</span>; i++) &#123;</span><br><span class="line">  userList.add(user);</span><br><span class="line">&#125;</span><br><span class="line">redisTemplate.opsForValue().set(<span class="string">"serializer"</span>, JSON.toJSONString(userList),<span class="number">5</span>,TimeUnit.MINUTES);</span><br><span class="line"><span class="keyword">long</span> end = System.currentTimeMillis();</span><br><span class="line">System.out.println(<span class="string">"Serializer序列化需要的时间:"</span> + (end - start));</span><br></pre></td></tr></table></figure>
<p>测试后:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">jackson2JsonRedisSerializer序列化需要的时间:687</span><br><span class="line">genericJackson2JsonRedisSerializer序列化需要的时间:22</span><br></pre></td></tr></table></figure>

<h3 id="总结-1"><a href="#总结-1" class="headerlink" title="总结"></a>总结</h3><ul>
<li><p>使用<code>Jackson2JsonRedisSerializer</code>需要指明序列化的类Class，可以使用<code>Obejct.class</code></p>
</li>
<li><p>使用<code>GenericJackson2JsonRedisSerializer</code>和<code>Jackson2JsonRedisSerializerdo</code>都可以正常序列化非泛型数组对象。<code>GenericJackson2JsonRedisSerializer</code>也可以正常反序列化非泛型数组对象，但是<code>Jackson2JsonRedisSerializerdo</code>因为“序列化带泛型的数据时，会以map的结构进行存储，反序列化时不能将map解析成对象”，所以不能反序列化，解决办法: 存储以JSON字符串存储</p>
</li>
<li><p>使用<code>GenericJacksonRedisSerializer</code>比<code>Jackson2JsonRedisSerializer</code>效率高</p>
</li>
<li><p><code>GenericJacksonRedisSerializer</code>和<code>Jackson2JsonRedisSerializer</code>都是以JSON格式去存储数据，都可以作为Redis的序列化方式</p>
</li>
</ul>
<h2 id="demo测试地址"><a href="#demo测试地址" class="headerlink" title="demo测试地址"></a>demo测试地址</h2><blockquote>
<p><a href="https://gitee.com/fengzxia/spring-boot-redis-cache/blob/master/src/test/java/com/lx/TestSerializer.java" target="_blank" rel="noopener">https://gitee.com/fengzxia/spring-boot-redis-cache/blob/master/src/test/java/com/lx/TestSerializer.java</a></p>
</blockquote>
<h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><blockquote>
<p><a href="https://blog.csdn.net/neosmith/article/details/46800235" target="_blank" rel="noopener">https://blog.csdn.net/neosmith/article/details/46800235</a><br><a href="https://blog.csdn.net/bai_bug/article/details/81222519" target="_blank" rel="noopener">https://blog.csdn.net/bai_bug/article/details/81222519</a></p>
</blockquote>

<div id="gitalk-container"></div>
<script src="https://cdn.bootcss.com/blueimp-md5/2.12.0/js/md5.min.js"></script><link rel="stylesheet" href="https://unpkg.com/gitalk/dist/gitalk.css"><script src="https://unpkg.com/gitalk/dist/gitalk.min.js"></script>

		<script>
		var gitalkConfig = {"clientID":"28a065e3b5afee156f4f","clientSecret":"e18104d6f3219526491fc42c892ff6a26b8f3e74","repo":"blog_comment","owner":"FENG1000","admin":["FENG1000"],"distractionFreeMode":false};
	    gitalkConfig.id = md5(location.pathname);
		var gitalk = new Gitalk(gitalkConfig);
	    gitalk.render("gitalk-container");
	    </script>
    
  <blockquote>
      <p>
          作者: 只是学习学习<br>
          邮箱: fengzxia1000@163.com<br>
          原文地址: <a href="https://fengzxia.gitee.io/posts/f6f65c4b.html" target="_blank" rel="noopener">https://fengzxia.gitee.io/posts/f6f65c4b.html</a><br>
          版权声明: 商业转载请联系作者获得授权，非商业转载请注明出处。
      </p>
  </blockquote>

  <script>
      function setClipboardText(event){
          // clipboardData 对象是为通过编辑菜单、快捷菜单和快捷键执行的编辑操作所保留的，也就是你复制或者剪切内容
          let clipboardData = event.clipboardData || window.clipboardData;
          // 如果未复制或者未剪切，则return出去
          if (!clipboardData) { return; }
          event.preventDefault();
          // Selection 对象，表示用户选择的文本范围或光标的当前位置。
          //     声明一个变量接收 -- 用户输入的剪切或者复制的文本转化为字符串
          let text = window.getSelection().toString();

          if (text) {
            // 如果文本存在则先取消文本默认事件
            event.preventDefault();
            // 通过调用常clipboardData对象的 setData(format, data) 方法；来设置相关文本
            // format: 一个DOMString 表示要添加到 drag object的拖动数据的类型。
            // data: 一个 DOMString表示要添加到 drag object的数据。
            var copyright = '\n\n'
                            + '\n著作权归作者所有。'
                            + '\n商业转载请联系作者获得授权，非商业转载请注明出处。'
                            + '\n作者: 只是学习学习'
                            + '\n邮箱: fengzxia1000@163.com'
                            + '\n原文地址: https://fengzxia.gitee.io/posts/f6f65c4b.html'

            clipboardData.setData('text/plain', text + copyright);

          }
      };
      var contents = document.getElementsByClassName("content");
      // 监听文章内容的copy事件
      contents[0].addEventListener('copy',function(e){
          setClipboardText(e);
      });
  </script>

  </div>
</article>




        
          <div id="footer-post-container">
  <div id="footer-post">

    <div id="nav-footer" style="display: none">
      <ul>
         
          <li><a href="/">主页</a></li>
         
          <li><a href="/archives/">归档</a></li>
         
          <li><a href="/categories/">分类</a></li>
         
          <li><a href="/tags/">标签</a></li>
         
          <li><a href="/search/">搜索</a></li>
         
          <li><a href="/about/">关于</a></li>
         
          <li><a href="/friend_ship/">友链</a></li>
        
      </ul>
    </div>

    <div id="toc-footer" style="display: none">
      <ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#应用场景"><span class="toc-number">1.</span> <span class="toc-text">应用场景</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#序列化问题"><span class="toc-number">2.</span> <span class="toc-text">序列化问题</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#分析"><span class="toc-number">3.</span> <span class="toc-text">分析</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#总结"><span class="toc-number">4.</span> <span class="toc-text">总结</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Jackson2JsonRedisSerializer和GenericJackson2JsonRedisSerializer的区别"><span class="toc-number">5.</span> <span class="toc-text">Jackson2JsonRedisSerializer和GenericJackson2JsonRedisSerializer的区别</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#一、使用Jackson2JsonRedisSerializer序列化反序列化带泛型的List数据"><span class="toc-number">5.1.</span> <span class="toc-text">一、使用Jackson2JsonRedisSerializer序列化反序列化带泛型的List数据</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#二、使用GenericJackson2JsonRedisSerializer序列化反序列化带泛型的List数据"><span class="toc-number">5.2.</span> <span class="toc-text">二、使用GenericJackson2JsonRedisSerializer序列化反序列化带泛型的List数据</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#四、GenericJackson2JsonRedisSerializer和Jackson2JsonRedisSerializerdo效率"><span class="toc-number">5.3.</span> <span class="toc-text">四、GenericJackson2JsonRedisSerializer和Jackson2JsonRedisSerializerdo效率</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#总结-1"><span class="toc-number">5.4.</span> <span class="toc-text">总结</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#demo测试地址"><span class="toc-number">6.</span> <span class="toc-text">demo测试地址</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#参考"><span class="toc-number">7.</span> <span class="toc-text">参考</span></a></li></ol>
    </div>

    <div id="share-footer" style="display: none">
      <ul>
  <li><a class="icon" href="http://www.facebook.com/sharer.php?u=https://fengzxia.gitee.io/posts/f6f65c4b.html" target="_blank" rel="noopener"><i class="fab fa-facebook fa-lg" aria-hidden="true"></i></a></li>
  <li><a class="icon" href="https://twitter.com/share?url=https://fengzxia.gitee.io/posts/f6f65c4b.html&text=使用Spring Cache + Redis + Jackson Serializer缓存数据库查询结果中序列化问题的处理" target="_blank" rel="noopener"><i class="fab fa-twitter fa-lg" aria-hidden="true"></i></a></li>
  <li><a class="icon" href="http://www.linkedin.com/shareArticle?url=https://fengzxia.gitee.io/posts/f6f65c4b.html&title=使用Spring Cache + Redis + Jackson Serializer缓存数据库查询结果中序列化问题的处理" target="_blank" rel="noopener"><i class="fab fa-linkedin fa-lg" aria-hidden="true"></i></a></li>
  <li><a class="icon" href="https://pinterest.com/pin/create/bookmarklet/?url=https://fengzxia.gitee.io/posts/f6f65c4b.html&is_video=false&description=使用Spring Cache + Redis + Jackson Serializer缓存数据库查询结果中序列化问题的处理" target="_blank" rel="noopener"><i class="fab fa-pinterest fa-lg" aria-hidden="true"></i></a></li>
  <li><a class="icon" href="mailto:?subject=使用Spring Cache + Redis + Jackson Serializer缓存数据库查询结果中序列化问题的处理&body=Check out this article: https://fengzxia.gitee.io/posts/f6f65c4b.html"><i class="fas fa-envelope fa-lg" aria-hidden="true"></i></a></li>
  <li><a class="icon" href="https://getpocket.com/save?url=https://fengzxia.gitee.io/posts/f6f65c4b.html&title=使用Spring Cache + Redis + Jackson Serializer缓存数据库查询结果中序列化问题的处理" target="_blank" rel="noopener"><i class="fab fa-get-pocket fa-lg" aria-hidden="true"></i></a></li>
  <li><a class="icon" href="http://reddit.com/submit?url=https://fengzxia.gitee.io/posts/f6f65c4b.html&title=使用Spring Cache + Redis + Jackson Serializer缓存数据库查询结果中序列化问题的处理" target="_blank" rel="noopener"><i class="fab fa-reddit fa-lg" aria-hidden="true"></i></a></li>
  <li><a class="icon" href="http://www.stumbleupon.com/submit?url=https://fengzxia.gitee.io/posts/f6f65c4b.html&title=使用Spring Cache + Redis + Jackson Serializer缓存数据库查询结果中序列化问题的处理" target="_blank" rel="noopener"><i class="fab fa-stumbleupon fa-lg" aria-hidden="true"></i></a></li>
  <li><a class="icon" href="http://digg.com/submit?url=https://fengzxia.gitee.io/posts/f6f65c4b.html&title=使用Spring Cache + Redis + Jackson Serializer缓存数据库查询结果中序列化问题的处理" target="_blank" rel="noopener"><i class="fab fa-digg fa-lg" aria-hidden="true"></i></a></li>
  <li><a class="icon" href="http://www.tumblr.com/share/link?url=https://fengzxia.gitee.io/posts/f6f65c4b.html&name=使用Spring Cache + Redis + Jackson Serializer缓存数据库查询结果中序列化问题的处理&description=" target="_blank" rel="noopener"><i class="fab fa-tumblr fa-lg" aria-hidden="true"></i></a></li>
  <li><a class="icon" href="https://news.ycombinator.com/submitlink?u=https://fengzxia.gitee.io/posts/f6f65c4b.html&t=使用Spring Cache + Redis + Jackson Serializer缓存数据库查询结果中序列化问题的处理" target="_blank" rel="noopener"><i class="fab fa-hacker-news fa-lg" aria-hidden="true"></i></a></li>
</ul>

    </div>

    <div id="actions-footer">
        <a id="menu" class="icon" href="#" onclick="$('#nav-footer').toggle();return false;"><i class="fas fa-bars fa-lg" aria-hidden="true"></i> 菜单</a>
        <a id="toc" class="icon" href="#" onclick="$('#toc-footer').toggle();return false;"><i class="fas fa-list fa-lg" aria-hidden="true"></i> 目录</a>
        <a id="share" class="icon" href="#" onclick="$('#share-footer').toggle();return false;"><i class="fas fa-share-alt fa-lg" aria-hidden="true"></i> 分享</a>
        <a id="top" style="display:none" class="icon" href="#" onclick="$('html, body').animate({ scrollTop: 0 }, 'fast');"><i class="fas fa-chevron-up fa-lg" aria-hidden="true"></i> 返回顶部</a>
    </div>

  </div>
</div>

        
        <footer id="footer">
  <div class="footer-left">
    Copyright &copy;
    
    
    2019-2020
    只是学习学习
  </div>
  <div class="footer-right">
    <nav>
      <ul>
         
          <li><a href="/">主页</a></li>
         
          <li><a href="/archives/">归档</a></li>
         
          <li><a href="/categories/">分类</a></li>
         
          <li><a href="/tags/">标签</a></li>
         
          <li><a href="/search/">搜索</a></li>
         
          <li><a href="/about/">关于</a></li>
         
          <li><a href="/friend_ship/">友链</a></li>
        
      </ul>
    </nav>
  </div>
</footer>

    </div>
    <!-- styles -->

<link rel="stylesheet" href="/lib/font-awesome/css/all.min.css">


<link rel="stylesheet" href="/lib/justified-gallery/css/justifiedGallery.min.css">


    <!-- jquery -->

<script src="/lib/jquery/jquery.min.js"></script>


<script src="/lib/justified-gallery/js/jquery.justifiedGallery.min.js"></script>

<!-- clipboard -->

  
<script src="/lib/clipboard/clipboard.min.js"></script>

  <script type="text/javascript">
  $(function() {
    // copy-btn HTML
    var btn = "<span class=\"btn-copy tooltipped tooltipped-sw\" aria-label=\"复制到粘贴板!\">";
    btn += '<i class="far fa-clone"></i>';
    btn += '</span>'; 
    // mount it!
    $(".highlight table").before(btn);
    var clip = new ClipboardJS('.btn-copy', {
      text: function(trigger) {
        return Array.from(trigger.nextElementSibling.querySelectorAll('.code')).reduce((str,it)=>str+it.innerText+'\n','')
      }
    });
    clip.on('success', function(e) {
      e.trigger.setAttribute('aria-label', "复制成功!");
      e.clearSelection();
    })
  })
  </script>


<script src="/js/main.js"></script>

<!-- search -->

<!-- Google Analytics -->

<!-- Baidu Analytics -->

    <script type="text/javascript">
        var _hmt = _hmt || [];
        (function() {
            var hm = document.createElement("script");
            hm.src = "https://hm.baidu.com/hm.js?54382acbd8c4bc66535bce135e0ac166";
            var s = document.getElementsByTagName("script")[0];
            s.parentNode.insertBefore(hm, s);
        })();
    </script>

<!-- Disqus Comments -->


</body>
<script>
(function(){
    var bp = document.createElement('script');
    var curProtocol = window.location.protocol.split(':')[0];
    if (curProtocol === 'https'){
   bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
  }
  else{
  bp.src = 'http://push.zhanzhang.baidu.com/push.js';
  }
    var s = document.getElementsByTagName("script")[0];
    s.parentNode.insertBefore(bp, s);
})();
</script>
</html>
